from sqlalchemy import or_, text


class Crud:

    def __init__(self, model, keyword_fields: list = None):
        self.model = model
        self.keyword_fields = keyword_fields

    def keyword_query(self, query, q):
        """关键词搜索"""
        if q and self.keyword_fields:
            return query.filter(or_(*[getattr(self.model, field).like(f'{q}%') for field in self.keyword_fields]))
        return query

    def get_item(self, session, id: str = None, filter_: list = None):
        """获取单条数据"""
        if id is not None:
            return session.query(self.model).filter(self.model.id == id).first()
        if filter_ is not None:
            return session.query(self.model).filter(*filter_).first()
        return session.query(self.model).first()

    def create_item(self, session, body, commit=True):
        """创建单条数据"""
        item = self.model(**body)
        session.add(item)
        session.flush()
        if commit:
            session.commit()
        return item

    def update_item(self, session, update: dict, id: str = None, filter_: list = None, commit=True):
        """修改单条数据"""
        item = self.get_item(session, id=id, filter_=filter_)
        for k, v in update.items():
            if getattr(item, k) == v:
                continue
            setattr(item, k, v)

        if commit:
            session.commit()
        return item

    # 批量操作
    def get_items(self,  session, q: str = None, filter_: list = None, page: int = None, page_size: int = None,
                  order_by: str = None):
        """筛选多条"""
        query = session.query(self.model).filter()
        query = self.keyword_query(query, q)
        if filter_:
            query = query.filter(*filter_)

        if order_by:
            query = query.order_by(text(order_by))

        if page and page_size:
            query = query.offset((page - 1) * page_size).limit(page_size)
        return query

    def delete_items(self, session, ids, commit=True):
        """批量删除"""
        count = session.query(self.model).filter(self.model.id.in_(ids)).delete()
        if commit:
            session.commit()
        return count

    def get_page_items(self,  session, q: str = None, filter_: list = None, page: int = None, page_size: int = None,
                       order_by: str = None):
        """返回http"""
        query = self.get_items(session=session, q=q, filter_=filter_, page=page, page_size=page_size, order_by=order_by)
        return {'page': page, 'page_size': page_size, 'total': query.count(), 'data': query.all()}
